﻿using AutoMapper;
using Azure.Core.Serialization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Caching.Memory;
using System.Collections;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text.Json;
using WebApiThird.Entity;
using WebApiThird.IService;
using WebApiThird.Model;
using Zack.ASPNETCore;

namespace WebApiThird.Service
{
    public class StudentService : IStudentService
    {
        private readonly AppDbContext dbContext;
        private readonly IMapper mapper;
        private readonly IMemoryCache cache;
        private readonly IDistributedCache distributedCache;
        private readonly IMemoryCacheHelper memoryCacheHelper;
        private readonly IDistributedCacheHelper distributedCacheHelper;

        public StudentService(AppDbContext dbContext, IMapper mapper, IMemoryCache cache, IDistributedCache distributedCache,IMemoryCacheHelper memoryCacheHelper, IDistributedCacheHelper distributedCacheHelper)
        {
            this.dbContext = dbContext;
            this.mapper = mapper;
            this.cache = cache;
            this.distributedCache = distributedCache;
            this.memoryCacheHelper = memoryCacheHelper;
            this.distributedCacheHelper = distributedCacheHelper;
        }

        public async Task<bool> Add(StudentReq req)
        {
            var student = mapper.Map<Student>(req);
            dbContext.Students.Add(student);
            await dbContext.SaveChangesAsync();
            return true;
        }

        /// <summary>
        /// 内存缓存
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<StudentRes?> GetStudent(int id)
        {
            var result =await cache.GetOrCreateAsync($"student:{id}", async (e) =>
            {
                var student = await dbContext.Students.Where(p => p.Id == id).FirstOrDefaultAsync();
                var result = mapper.Map<StudentRes>(student);
               // e.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(10);
                e.SlidingExpiration = TimeSpan.FromSeconds(Random.Shared.Next(10,15));
                Console.WriteLine($"数据中查找数据{id}");
                return result;
            });
            
            return result;
        }


        /// <summary>
        /// 封装内存缓存使用
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<StudentRes?> GetStudentExt(int id)
        {
            var result = await memoryCacheHelper.GetOrCreateAsync($"students:{id}", async (e) =>
            {
                var student = await dbContext.Students.Where(p => p.Id == id).FirstOrDefaultAsync();
                var result = mapper.Map<StudentRes>(student);
                Console.WriteLine($"数据中查找数据{id}");
                return result;
            },15);

            return result;
        }

        /// <summary>
        ///  分布式缓存
        /// </summary>
        /// <returns></returns>
        public async Task<List<Student>?> GetStudents(int id)
        {
            string key = $"Students:List:greater{id}";
            var listStr = await distributedCache.GetStringAsync(key);
            if(string.IsNullOrWhiteSpace(listStr))
            {
                Console.WriteLine("数据库中取数据...");
                var students = dbContext.Students.Where(p => p.Id > id);
                var list = await students.ToListAsync();
                listStr = JsonSerializer.Serialize(list);
                await distributedCache.SetStringAsync(key,listStr,new DistributedCacheEntryOptions()
                {
                    SlidingExpiration = TimeSpan.FromSeconds(20),
                    AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(Random.Shared.Next(40,60))
                });

                return list;
            }
            else
            {
                var list = JsonSerializer.Deserialize<List<Student>>(listStr);
                await distributedCache.RefreshAsync(key);
                return list;
            }
        }


        /// <summary>
        ///  分布式缓存
        /// </summary>
        /// <returns></returns>
        public async Task<List<Student>?> GetStudentsExt(int id)
        {
            string key = $"Students:List:greater{id}";
            return await distributedCacheHelper.GetOrCreateAsync<List<Student>?>(key, async e => {

                Console.WriteLine("数据库中取数据...");
                var students = dbContext.Students.Where(p => p.Id > id);
                var list = await students.ToListAsync();
                e.SlidingExpiration = TimeSpan.FromSeconds(10);
                return list;
            }, 30);
        }

    }
}
